/**
 * @file mutate.c
 * @brief Functions for mutating a module
 * @author Scott Moyers
 * @date 2009
 */

#include "mutate.h"
#include "util.h"

#include <limits.h>
#include <assert.h>
#include <string.h>

/** mutation function pointer array to make selecting mutation functions easy */
MutationFunc mutation_functions[MUT_FUNCS] = {
	&move_wire,
	&change_gate_type,
};

MutationFunc get_mutation_func(const char *func)
{
	if (!strcmp(func, "move_wire")) {
		return &move_wire;
	} else if (!strcmp(func, "change_gate_type")) {
		return &change_gate_type;
	}
	return NULL;
}

int move_wire(dsfmt_t *dsfmt, struct Module *m)
{
	int n = (int) (dsfmt_genrand_close_open(dsfmt) * m->num_gates);
	struct Gate* g = &m->circuit[n];
	unsigned int inps = num_gate_inputs(g);
	if (inps > 0) {
		int r = (int) (dsfmt_genrand_close_open(dsfmt) * inps);
		int nr = (int) (dsfmt_genrand_close_open(dsfmt) * n);
		g->in[r] = nr;
		m->id = next_module_id();
		return 0;
	}
	return 1;
}

int change_gate_type(dsfmt_t *dsfmt, struct Module *m)
{
	int n = (int) (dsfmt_genrand_close_open(dsfmt) * m->num_gates);
	struct Gate* g = &m->circuit[n];
	g->gate_type = (int) (dsfmt_genrand_close_open(dsfmt) * GATE_TYPES);
	m->id = next_module_id();
	return 0;
}
